from location import Estate

class Card:
    def __init__(self,manager,player):
        self.player=player
        self.manager=manager

class Barrier(Card):
    def action(self,pos):
        self.manager.regPassby(pos,'Barrier',self.passby)

    def run(self):
        check=lambda x: not x or abs(int(x))<=self.manager.config.data.barrierRange
        in_=self.manager.game.getInput(prompt="Input the position.",check=check)
        if not in_:
            return False

        self.pos=self.player.pos+int(in_)

        self.action(self.pos)
        return True

    def passby(self,player):
        self.manager.unregPassby(self.pos)

        return True

class StayCard(Card):
    def run(self):
        self.action()

        return True

    def action(self):
        self.origToss=self.player.toss
        self.player.toss=self.toss

    def toss(self):
        self.player.toss=self.origToss

        return 0

class RemoteDice(Card):
    def run(self):
        step=int(self.manager.game.getInput(
                prompt="Please remote your dice.",
                check=lambda x:not x or 1<=int(x)<=6,
                errorMsg="Dice result not valid.",
                ) or -1)

        if step==-1:
            return False

        self.action(step)
        return True

    def action(self,step):
        self.step=step
        self.origToss=self.player.toss
        self.player.toss=self.toss

    def toss(self):
        self.player.toss=self.origToss

        return self.step

    def run(self):
        self.action()

        return True

class SMCard(Card):
    def run(self):
        if hasattr(self,'preRun'):
            self.preRun()

        self.action()
        return True

    def action(self):

        self.origStop=self.player.stop
        self.player.stop=self.stop
        setattr(self.player,self.attrname,self.initRounds)

    def stop(self,loc):
        player=self.player

        setattr(player,self.attrname,getattr(player,self.attrname)-1)

        self.stopEvent(self,loc,player)

        if not getattr(player.self.attrname):
            player.stop=self.origStop


class GroundCard(Card):
    attrname="_groundRounds"
    initRounds=5

    def stopEvent(self,loc,player):

        if isinstance(loc,Estate) and loc.owner!=player:
            if loc.owner is not None:
                loc.run(player)
                loc.owner.estates.remove(loc)

            loc.owner=player
            player.estates.append(loc)
            self.manager.game.showText("Estate occupied.")

        loc.run(player)

class ObjCard(Card):
    def run(self):
        objList=[(player.pos,player) for player in self.manager.game.players if self.player.pos-5<=player.pos<self.player.pos+5]
        objList.sort()
        objList=[player for pos,player in objList]
        
        choiceList=[(player.name+(' (self)' if player==self.player else '')+'.',player) for player in objList]

        obj=self.manager.game.choice(
                choiceList,
                prompt="Objects:",
                )

        if obj==-1:
            return False

        return self.action(obj)

class TurtleCard(ObjCard):
    def action(self,obj):
        self.obj=obj

        self.origToss=obj.toss
        obj.toss=self.toss

        obj._turtleRounds=3
        return True

    def toss(self):
        obj=self.obj
        obj._turtleRounds-=1

        if not obj._turtleRounds:
            obj.toss=self.origToss

        return 1

class ReverseCard(Card):
    def run(self):
        self.action()

        return True

    def action(self):
        self.player.dir_*=-1

class BuyEstateCard(Card):
    def run(self):
        pos=self.player.pos
        loc=self.manager.gameMap[pos]

        if not isinstance(loc,Estate) or loc.owner==self.player:
            return False

        return self.action(loc)

    def action(self,estate):
        cost=estate.value()

        if cost>self.player.cash:
            self.manager.game.showText("Cash not enough. Fail. Shame.")
            return False

        self.manager.game.showText("Buying the estate for {}.".format(cost))
        estate.owner.estates.remove(estate)
        estate.owner.cash+=cost
        self.player.cash-=cost
        estate.owner=self.player
        self.player.estates.append(estate)

        return True

class TaxCard(ObjCard):
    def action(self,obj):
        obj.saving-=int(obj.saving*0.3)

        return True

class LootCard(ObjCard):
    def action(self,obj):
        l=[]

        for (code,amount) in obj.inv.items():
            l.extend([code]*amount)

        if not l:
            self.manager.game.showText("The object has nothing to loot.")
            return False

        victim=random.choice(l)
        self.player.inv[victim]+=1
        obj.inv[victim]-=1

        return True

class DestoryCard(Card):
    def run(self):
        pos=self.player.pos
        loc=self.manager.gameMap[loc]

        if not isinstance(loc,Estate):
            return False
        
        self.action(loc.street)
        return True

    def action(self,code):
        street=self.manager.gameMap[code]

        for estate in street:
            if estate.owner is not None:
                estate.owner.cash+=int(estate.value()*1.5)

                estate.owner=None

        self.manager.game.showText("The street is destoried and the landowners has been compensated.")

class MonsterCard(Card):
    def run(self):
        pos=self.player.pos
        loc=self.manager.gameMap[loc]

        if not isinstance(loc,Estate):
            return False
        
        self.action(loc.street)
        return True

    def action(self,code):
        street=self.manager.gameMap[code]

        for estate in street:
            estate.level=1

        self.manager.game.showText("A monster has attacked the street. All estates has been cracked into level 1.")

class WealthCard(SMCard):
    attrname="_wealthRounds"
    initRounds=8

    def preRun(self):
        self.manager.game.showText("May wealth be with you.")
        self.player.cash+=10000

    def stopEvent(self,loc,player):
        if isinstance(loc,Estate) and loc.owner!=player and loc.owner is not None:
            pass
        else :
            loc.run(player)

class HappinessCard(SMCard):
    attrname="_happinessRounds"
    initRounds=8

    def preRun(self):
        self.manager.game.showText("May happiness be with you.")
        for i in range(5):
            self.player.inv[self.manager.randomCard()]+=1

    def stopEvent(self,loc,player):
        if isinstance(loc,Estate) and loc.owner!=player and loc.owner is not None:
            pass
        else :
            loc.run(player)

class LotteryCard(Card):
    def run(self):
        check = lambda x: not x or 1<=int(x)<=20

        number=self.manager.game.getInput(
                prompt="Please input the number you want to be taken.",
                check=check,
                )

        if not number:
            return False
        else:
            self.action(int(number))
            return True

    def action(self,number):
        self.manager.lotteryCheat=number
        
class AverageCard(Card):
    def run(self):
        newCash=sum([p.cash for p in self.manager.game.players])/len(self.manager.game.players)

        for player in self.manager.game.players:
            player.cash=newCash

        self.manager.game.showText("Cash has been devided.")
        return True
